package com.javafactroy.kunlong.base.metadata.model;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.javafactroy.kunlong.base.config.datasource.mysql.MysqlDatasourceConfig;
import com.javafactroy.kunlong.base.metadata.valueobj.MetadataField;
import com.javafactroy.kunlong.base.metadata.valueobj.MetadataTable;
import com.javafactroy.kunlong.codefactroy.convert.TmetadataFieldConvert;
import com.javafactroy.kunlong.data.dao.mysql.MysqlTablesMapper;
import com.javafactroy.kunlong.data.entity.mysql.MysqlColumns;
import com.javafactroy.kunlong.base.context.ApiContext;
import com.javafactroy.kunlong.data.dao.mysql.MysqlColumnsMapper;
import com.javafactroy.kunlong.data.entity.mysql.MysqlTables;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.persistence.Table;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
@Primary
public class TMetadataModel {

    @Autowired
    MysqlDatasourceConfig mysqlDatasourceConfig;

    @Autowired
    MysqlTablesMapper mysqlTablesMapper;

    @Autowired
    MysqlColumnsMapper mysqlColumnsMapper;

    public List<MysqlColumns> selectMysqlColumns(String tableName) {
        PageHelper.orderBy("ORDINAL_POSITION asc");
        //SqlSessionFactory sessionFactory = ApiContext.INST.getMysqlSessionFactory();

        List<MysqlColumns> list = mysqlColumnsMapper.select(new MysqlColumns().setDbName(mysqlDatasourceConfig.getDbName()).setTableName(tableName));
        //ret.forEach(i -> i.setPropName(StrUtil.toCamelCase(i.getColName())));
        return list;
    }

    public List<MysqlTables> selectMysqlTables(String tableName) {

        return mysqlTablesMapper.select(new MysqlTables().setDbName(mysqlDatasourceConfig.getDbName()).setTableName(tableName));

    }


    public MetadataTable loadDbMysqlMetadata(String tableName) {
        List<MysqlColumns> columns = selectMysqlColumns(tableName);
        List<MetadataField> fields = TmetadataFieldConvert.INSTANCE.fromList(columns);
        fields.forEach(i -> {
            i.setPropName(StrUtil.toCamelCase(i.getColName()));
            i.setPropType(i.dataType2PropType());
            i.setJdbcType(i.datatype2JdbcType());
        });
        String dbName = mysqlDatasourceConfig.getDbName();
        List<MysqlTables>  tables=selectMysqlTables(tableName);
        String tableComment=tableName;
        if(ObjectUtil.isNotEmpty(tables)){
            tableComment=tables.get(0).getTableComment();
        }
        return new MetadataTable().setTableComment(tableComment).setDbName(dbName).setTableName(tableName).setFieldList(fields);

    }

    public <T> void check(T data) {
        String tableName = getTableName(data);
        MetadataTable tmetadataTable = findMetadata(tableName);
        tmetadataTable.getFieldList().forEach(i -> {
            if (i.getColType().equals("VARCHAR")) {
                //i.getLength();
                checkStr(i, data);
            }
        });

    }

    <T> void checkStr(MetadataField i, T data) {
        //i.getLength();
        Object v = ReflectUtil.getFieldValue(data, i.getPropName());
        if (v != null && v.toString().length() > i.getMaxLength() / 3) {
            throw new RuntimeException(StrUtil.format("{} 超长{}", i.getPropName(), i.getMaxLength() / 3));
        }

    }

    <T> String getTableName(T data) {
        Table table = data.getClass().getAnnotation(Table.class);
        if (table != null) {
            return table.name();
        }
        return "";
    }

    public <T> Map<String, Field> parse(T data) {
        Map<String, Field> map = ReflectUtil.getFieldMap(data.getClass());
        return map;
    }

    public MetadataTable findMetadata(String tableName) {
        MetadataTable tmetadataTable = new MetadataTable();
        tmetadataTable.setTableName(tableName);
        SqlSessionFactory sessionFactory = ApiContext.INST.getMysqlSessionFactory();

        try (SqlSession session = sessionFactory.openSession()) {

            Connection connection = session.getConnection();
            // 创建Statement对象
            Statement statement = connection.createStatement();
            // 执行SQL查询语句
            String sql = StrUtil.format("SELECT * FROM {} limit 0", tableName);
            ResultSet resultSet = statement.executeQuery(sql);
            // 获取结果集的元数据
            ResultSetMetaData metaData = resultSet.getMetaData();

            com.mysql.cj.jdbc.result.ResultSetMetaData rowSetMetaData = (com.mysql.cj.jdbc.result.ResultSetMetaData) metaData;
            log.info("{}", rowSetMetaData);
            for (com.mysql.cj.result.Field field : rowSetMetaData.getFields()) {
                String propName = StrUtil.toCamelCase(field.getName());
                tmetadataTable.getFieldList().add(new MetadataField().setPropName(propName).setMaxLength(field.getLength()).setColName(field.getName()).setColType(field.getMysqlType().getName()));
            }
            // 获取字段数量
            // int columnCount = m etaData.getColumnCount();
            resultSet.close();
            statement.close();
            connection.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return tmetadataTable;
    }
}
